package com.service.socket.protocol;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class Conversion {

	public static String getCrc(String hexstr) {
		char chCRCHi = 0xFF; // 高CRC字节初始化
		char chCRCLo = 0xFF; // 低CRC字节初始化
		int wIndex; // CRC循环中的索引
		char[] data = HexStringToChars(hexstr);
		int wDataLen = data.length;
		int n = 0;
		while (n < wDataLen) {
			wIndex = chCRCLo ^ data[n++];
			chCRCLo = (char) (chCRCHi ^ chCRCHTalbe[wIndex]);
			chCRCHi = chCRCLTalbe[wIndex];
		}
		String lString = Integer.toHexString(chCRCLo);
		if (lString.length() < 2)
			lString = "0" + lString;
		String rString = Integer.toHexString(chCRCHi);
		if (rString.length() < 2)
			rString = "0" + rString;
		return lString + rString;
	}

	private static char[] chCRCHTalbe = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
			0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,
			0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
			0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
			0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
			0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00,
			0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
			0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
			0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
			0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
			0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
			0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80,
			0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
			0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,
			0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
			0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80,
			0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
			0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00,
			0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
			0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
			0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
			0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
			0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
			0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 };

	private static char[] chCRCLTalbe = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03,
			0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC,
			0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B,
			0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA,
			0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
			0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11,
			0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
			0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD,
			0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9,
			0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
			0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5,
			0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20,
			0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6,
			0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF,
			0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
			0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F,
			0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7,
			0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50,
			0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
			0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E,
			0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48,
			0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D,
			0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86,
			0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40

	};

	private static int parse(char c) {
		if (c >= 'a') {
			return (c - 'a' + 10) & 0x0f;
		}

		if (c >= 'A') {
			return (c - 'A' + 10) & 0x0f;
		}
		return (c - '0') & 0x0f;
	}

	private static char[] HexStringToChars(String hexstr) {
		char[] b = new char[hexstr.length() / 2];
		int j = 0;
		for (int i = 0; i < b.length; i++) {
			char c0 = hexstr.charAt(j++);
			char c1 = hexstr.charAt(j++);
			b[i] = (char) ((parse(c0) << 4) | parse(c1));
		}

		return b;
	}

	/**
	 * 转议码
	 * @param bytes
	 * @return
	 */
	public static byte[] dataEncode(byte[] bytes) {
		byte[] newData = new byte[bytes.length + 10000];
		newData[0] = bytes[0];
		int k = 1;
		for (int i = 1; i < bytes.length - 1; i++) {
			if (bytes[i] == 0x55) {
				newData[k++] = 0x54;
				newData[k++] = 0x01;
			} else if (bytes[i] == 0x54) {
				newData[k++] = 0x54;
				newData[k++] = 0x02;
			} else {
				newData[k++] = bytes[i];
			}
		}
		newData[k++] = bytes[bytes.length - 1];
		byte[] b = Arrays.copyOf(newData, k);
		return b;
	}

	public static byte[] dataDecode(byte[] bytes) {
		byte[] newData = new byte[bytes.length];
		int k = 0;
		for (int i = 0; i < bytes.length; i++) {
			if (bytes[i] == 0x54 && bytes[i + 1] == 0x01) {
				newData[k++] = 0x55;
				i++;
			} else if (bytes[i] == 0x54 && bytes[i + 1] == 0x02) {
				newData[k++] = 0x54;
				i++;
			} else {
				newData[k++] = bytes[i];
			}
		}
		byte[] b = Arrays.copyOf(newData, k);
		return b;
	}

	public static byte[] hexStringToBytes(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));

		}
		return d;
	}

	public static String bytesToHexString(byte[] bytes) {
		StringBuffer buffer = new StringBuffer(bytes.length);
		String hexstr;
		for (byte b : bytes) {
			hexstr = Integer.toHexString(b & 0xFF);
			if (hexstr.length() == 1) {
				buffer.append("0");
			}
			buffer.append(hexstr.toUpperCase());
		}
		return buffer.toString();
	}

	public static String getcode(String result) {
		String codees = null;
		String[] codes = null;
		String code = null;
		if (result != null && result.trim().length() > 0) {
			codees = getStringForCode(result);
		}
		if (codees != null && codees.trim().length() > 0) {
			codes = codees.split(",");
		}
		if (codes != null && codes.length > 0) {
			code = codes[0];
		}
		return code;
	}

	public static String getStringForCode(String result) {
		String cc = null;
		try {
			byte[] resultbyte = new byte[result.length() / 2];
			for (int i = 0, j = 0; i < result.length(); i = i + 2) {
				String ss = result.substring(i, i + 2);
				int intv = Integer.parseInt(ss, 16);
				resultbyte[j++] = (byte) (intv);
			}
			cc = new String(resultbyte, "ISO-8859-1");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return cc;
	}

	private static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}

	public static String gb2312ToHexString(String str) {
		try {
			byte[] bytes = str.getBytes("gb2312");
			str = Conversion.bytesToHexString(bytes);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return str;
	}
	
	public static String utfToHexString(String str) {
		try {
			byte[] bytes = str.getBytes("utf-8");
			str = Conversion.bytesToHexString(bytes);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return str;
	}

	public static String hexStringToGb2312(String hexString) {
		try {
			byte[] bytes = Conversion.hexStringToBytes(hexString);
			hexString = new String(bytes, "gb2312");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return hexString;
	}

	public static String reversal(String str) {
		StringBuffer newStr = new StringBuffer();
		if (str.length() % 2 == 0) {
			int i = str.length() / 2;
			for (; i > 0; i--) {
				newStr.append(str.substring((i - 1) * 2, i * 2));
			}
		} else {
			newStr.append(str);
		}
		return newStr.toString();
	}

	public static String intToHexString(int x) {
		String str = Integer.toHexString(x);
		while (str.length() - 4 < 0) {
			str = "0" + str;
		}
		
		if(str.length() > 4){
			str = str.substring(0,4);
		}
		return Conversion.reversal(str);
	}

	/**
	  * 计算校验和<br>
	  * <p>对“消息头＋会话头＋事务头＋操作信息”按32位异或，对异或结果取反后的值为校验和。
	  * @param msg
	  * @return
	  */
	public static String checkSum(String hexString) {
		byte[] arr = hexStringToBytes(hexString);
		byte sum = 0x00;
        for (int i = 0; i < arr.length; i++)
        {
            sum += arr[i];
        }
        return byte2hex(sum);
	}
	 
    /**
     * 将单字节转成16进制<br>
     * @param b
     * @return
     */
    public static String byte2hex(byte b) {
        StringBuffer buf = new StringBuffer();
        char[] hexChars = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
                'D', 'E', 'F'
            };
        int high = ((b & 0xf0) >> 4);
        int low = (b & 0x0f);
        buf.append(hexChars[high]);
        buf.append(hexChars[low]);
        return buf.toString();
    }
    
    public static String padLeft(int length,String str,char add){
    	if(str==null){
    		str = "";
    	}
    	while(str.length()<length){
    		str=String.valueOf(add)+str;
    	}
    	return str;
    }
	    
	    /**  
	     * byte数组中取int数值，本方法适用于(低位在前，高位在后)的顺序，和和intToBytes（）配套使用 
	     *   
	     * @param src  
	     *            byte数组  
	     * @param offset  
	     *            从数组的第offset位开始  
	     * @return int数值  
	     */    
	 public static int bytesToInt(byte[] src, int offset) {  
	     int value;    
	     value = (int) ((src[offset] & 0xFF)   
	             | ((src[offset+1] & 0xFF)<<8)   
	             | ((src[offset+2] & 0xFF)<<16)   
	             | ((src[offset+3] & 0xFF)<<24));  
	     return value;  
	 }  
	   
	  /**  
	     * byte数组中取int数值，本方法适用于(低位在后，高位在前)的顺序。和intToBytes2（）配套使用 
	     */  
	 public static int bytesToInt2(byte[] src, int offset) {  
	     int value;    
	     value = (int) ( ((src[offset] & 0xFF)<<24)  
	             |((src[offset+1] & 0xFF)<<16)  
	             |((src[offset+2] & 0xFF)<<8)  
	             |(src[offset+3] & 0xFF));  
	     return value;  
	 }  

}
